<?php
/**
 * 
 * Navigation map
 * <code>
 * strtucture
 * |-[page_name] structure
 *    |-#id
 *    |-#content
 *    |-#children structure
 *      |-...
 * </code>
 * @package WNavigation
 *
 */
require_once 'WNavigator/errors.php';
class WN_Map {
	private $hieracy;
	private $sequence;
	private $index;
	private $map_filepath;
	private $seq_filepath;
	private $format;
	
	const MAPFILE = 'map.data';
	const SEQFILE = 'map.seq';	
	
	public function __construct($working_dir, $format = 'XML'){
		$this->map_filepath = $working_dir . DIRECTORY_SEPARATOR . self::MAPFILE;
		$this->seq_filepath = $working_dir . DIRECTORY_SEPARATOR . self::SEQFILE;
		$this->format       = $format;
		$this->init();
	}	
	
	public function addPage($path, $name, $content) {
		$page = $this->searchPage($path);
		print_r($page);
		if(!empty($page)) {
			$new_page = $this->newPage($content);
			var_dump($page->isExist('__children'));
			if(!$page->isExist('__children')) {
				$page->newValue('__children', new WK_Data_Map());
			}
			$page->newValue($name, $new_page, '__children');
			print_r($page);
			print_r($this->hieracy);
			return $new_page;
		}
	}
	
	public function updPage($path, $content){
		$this->searchPage($path)->setValue('__content', $content);		
	}
	
	public function getPage($path){
		$page = $this->searchPage($path);
		if(!empty($page)) {
			$data = new WK_Data_Map();
			$data->newValue('id',      $page->getValue('__id'));
			$data->newValue('content', $page->getValue('__content'));
			return $data;
		} 
		else {
			throw new WK_Error('Page ' . $path . ' not found!', WERR_PAGE_NOT_FOUND);
		}
	}
	
	public function delPage($path){
		$page = $this->hieracy->delValue($this->getSearchPath($path));
	}
	
	public function save(){
		WK_App::cmd('WFilesystem/write', array(
			'file'    => $this->map_filepath,
			'content' => WK_Data::serialize($this->hieracy, $this->format)));
		WK_App::cmd('WFilesystem/write', array(
			'file'    => $this->seq_filepath,
			'content' => $this->sequence));
	}
	
	public function nextId(){
		$this->sequence++;
		WK_App::cmd('WFilesystem/write', array(
			'file'    => $this->seq_filepath,
			'content' => $this->sequence));
		return $this->sequence;
	}
	
	public function toData(){
		return $this->hieracy;
	}
	
	public function __toString(){
		return (string) $this->hieracy;
	}
	
	private function newPage($content){
		$page = new WK_Data_Map();
		$page->newValue('__id', $this->nextId());
		$page->newValue('__content', $content);
		$page->newValue('__chlidren', new WK_Data_Map());
		return $page;
	}
	
	private function searchPage($path){		
		$page = $this->hieracy->getValue($this->getSearchPath($path));
		return $page;
	}
	
	private function getSearchPath($path){
		$path = preg_replace('#/+#', '/', trim('home/' . $path, '/'));
		$path = '/' . str_replace('/', '/__children/', $path);		
		return $path;
	}
	
	private function init(){
		try {
			$data = WK_App::get('file:' . $this->map_filepath)->getValue('content');
		}
		catch (WK_Error $e) {
			if($e->getCode() != WERR_FILE_NOT_FOUND) throw $e;
		}
		if(!empty($data))
			$this->hieracy = WK_Data::load($data, $this->format); 
		else 
			$this->hieracy = new WK_Data_Map();
			
		if(!$this->hieracy->isExist('/home')){
			$this->hieracy->newValue('home', $this->newPage('home_page_is_empty'));
		}
		
		try {
			$this->sequence = WK_App::get('file:' . $this->seq_filepath)->getValue('content');
		}
		catch(WK_Error $e){
			if($e->getCode() == WERR_FILE_NOT_FOUND) 
				$this->sequence = 0;
			else 
				throw $e;
		}		
	}
}